﻿// Owner: zhoub-g
// Co-Owner:
#include "CmdLookAround.h"
#include "IModelView.h"
#include "IDocument.h"
#include "IUiView.h"
#include "IPickPointAction.h"
#include "IGraphicsElementShape.h"
#include "UiDocumentViewUtils.h"
#include "IUserTransaction.h"
#include "RenderEnums.h"
#include "ICamera.h"
#include "IElementBasicInformation.h"
#include "ICanvas.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
#include "CommandRegister.h"
#include "GcmpCommandState.h"
#include "IUiDocumentViewManager.h"
#include "VisualUiViewMouseEventHandler.h"
#include "IUiViewMouseEvent.h"

using namespace gcmp;
using namespace Sample;

bool ActionLookAround::m_isRotating = false;

Sample::ActionLookAround::ActionLookAround()
{
    m_bShiftDown = false;
    m_nLineEditStep = 100;
    m_nLineEditStepPlus = 6;
    m_isRotating = true;

    IUiDocumentViewManager* pViewManager = IUiDocumentViewManager::Get();
    if (!pViewManager)
        return;
    IUiView* pUIView = pViewManager->GetCurrentUiView();
    if (!pUIView)
        return;
    IUiViewMouseEvent* pViewMouseEvent = pUIView->GetUiViewMouseEvent();
    pViewMouseEvent->Add(VisualUiViewMouseEventHandler::Get());
}

Sample::ActionLookAround::~ActionLookAround()
{
    m_isRotating = false;

    m_bShiftDown = false;
    m_nLineEditStep = 100;
    m_nLineEditStepPlus = 6;

    IUiDocumentViewManager* pViewManager = IUiDocumentViewManager::Get();
    if (!pViewManager)
        return;
    IUiView* pUIView = pViewManager->GetCurrentUiView();
    if (!pUIView)
        return;
    IUiViewMouseEvent* pViewMouseEvent = pUIView->GetUiViewMouseEvent();
    pViewMouseEvent->Delete(VisualUiViewMouseEventHandler::Get());
}

bool ActionLookAround::OnKeyDown(IUiView* pCurrentView, int nChar)
{
    if (IsKeyAndButtonPressed(VK_SHIFT))
    {
        m_bShiftDown = true;
    }
    else
    {
        m_bShiftDown = false;
    }

    if (nChar == 'W' || nChar == 'w')
    {
        int nStep = GetStep();
        MovePosition(eLookAroundFront, nStep);
    }
    else if (nChar == 'S' || nChar == 's')
    {
        int nStep = GetStep();
        MovePosition(eLookAroundBack, nStep);
    }
    else if (nChar == 'A' || nChar == 'a')
    {
        int nStep = GetStep();
        MovePosition(eLookAroundLeft, nStep);
    }
    else if (nChar == 'D' || nChar == 'd')
    {
        int nStep = GetStep();
        MovePosition(eLookAroundRight, nStep);
    }
    else if (nChar == 'Q' || nChar == 'q')
    {
        int nStep = GetStep();
        MovePosition(eLookAroundUp, nStep);
    }
    else if (nChar == 'E' || nChar == 'e')
    {
        int nStep = GetStep();
        MovePosition(eLookAroundDown, nStep);
    }
    else
    {
        ActionBase::OnKeyDown(pCurrentView, nChar);
    }
    return true;
}

//*------------------------------------------------------------------*/
// 描述：获得移动步长
//*------------------------------------------------------------------*/
int ActionLookAround::GetStep()
{
    int nStep(m_nLineEditStep);

    if (m_bShiftDown)
    {
        nStep *= m_nLineEditStepPlus;
    }

    return nStep;
}

//*------------------------------------------------------------------*/
// 描述：移动相机位置
//*------------------------------------------------------------------*/
void ActionLookAround::MovePosition(eMoveTypeLookAround nType, int nStep)
{
    IDocument* pDocument = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDocument, L"pDocument指针为空", L"GDMP", L"2020-03-22");

    IUiView* pUiView = UiDocumentViewUtils::GetCurrentUiView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiView, L"pUiView为空", L"GDMP", L"2020/06/10");

    // 获取相机
    ICanvas *pCanvas = pUiView->GetCanvas();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCanvas, L"pCanvas为空", L"GDMP", L"2021-02-22");
    ICamera* pCamera = pCanvas->GetCamera();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCamera, L"pCamera为空", L"GDMP", L"2020/06/10");

    CameraType type = CameraType::Perspective;
    Vector3d position;
    Vector3d direction;
    Vector3d upDirection;
    double aspectRatio = 0.0;
    double nearDist = 0.0;
    double farDist = 0.0;
    double fieldOfView = 0.0;
    double orthoWindowHeight = 0.0;
    pCamera->GetAllParameters(type,
        position, direction, upDirection,
        aspectRatio, nearDist, farDist,
        fieldOfView,
        orthoWindowHeight);

    Vector3d vMove;
    if (nType == eLookAroundFront)
    {
        vMove = direction * nStep;
    }
    else if (nType == eLookAroundBack)
    {
        vMove = direction * nStep * -1;
    }
    else if (nType == eLookAroundLeft)
    {
        Vector3d vRight = direction.Cross(upDirection);
        vMove = vRight * nStep * -1;
    }
    else if (nType == eLookAroundRight)
    {
        Vector3d vRight = direction.Cross(upDirection);
        vMove = vRight * nStep;
    }
    else if (nType == eLookAroundUp)
    {
        vMove = upDirection * nStep;
    }
    else if (nType == eLookAroundDown)
    {
        vMove = upDirection * nStep * -1;
    }    
    position += vMove;
    
    std::wstring sTmp;
    sTmp = L"KeyDown position(" + std::to_wstring(position.GetX()) + L"," + std::to_wstring(position.GetY()) + L"," + std::to_wstring(position.GetZ()) + L")";
    sTmp += L" direction(" + std::to_wstring(direction.GetX()) + L"," + std::to_wstring(direction.GetY()) + L"," + std::to_wstring(direction.GetZ()) + L")";
    sTmp += L" upDirection(" + std::to_wstring(upDirection.GetX()) + L"," + std::to_wstring(upDirection.GetY()) + L"," + std::to_wstring(upDirection.GetZ()) + L")\n";
    
    static bool bOutput = false;
    if (bOutput)
    {
        OutputDebugString(sTmp.c_str());
    }

    pCamera->SetAllParameters(type, position,
        direction, upDirection,
        aspectRatio, nearDist,
        farDist, fieldOfView,
        orthoWindowHeight);
}

REGISTER_COMMAND(CmdLookAround)

CmdLookAround::CmdLookAround()
    : CommandBase(L"CmdLookAround", true)
{
}

CmdLookAround::~CmdLookAround()
{
}

bool CmdLookAround::IsVisible() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

bool CmdLookAround::IsEnabled() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

OwnerPtr<gcmp::IAction> CmdLookAround::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    return  NEW_AS_OWNER_PTR(ActionLookAround);
}

REGISTER_COMMAND(CmdSwitchCamera)

CmdSwitchCamera::CmdSwitchCamera()
    : CommandBase(L"CmdSwitchCamera", true)
{
}

bool CmdSwitchCamera::IsVisible() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

bool CmdSwitchCamera::IsEnabled() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

OwnerPtr<gcmp::IAction> CmdSwitchCamera::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    IDocument* pDocument = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDocument, L"pDocument指针为空", L"GDMP", L"2020-03-22");

    IUiView* pUiView = UiDocumentViewUtils::GetCurrentUiView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiView, L"pUiView为空", L"GDMP", L"2020/06/10");

    // 获取相机
    ICanvas *pCanvas = pUiView->GetCanvas();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCanvas, L"pCanvas为空", L"GDMP", L"2021-02-22");
    ICamera* pCamera = pCanvas->GetCamera();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCamera, L"pCamera为空", L"GDMP", L"2020/06/10");

    static CameraType s_cameraType = CameraType::Perspective;

    Vector3d position;
    Vector3d direction;
    Vector3d upDirection;
    double aspectRatio = 0.0;
    double nearDist = 0.0;
    double farDist = 0.0;
    double fieldOfView = 0.0;
    double orthoWindowHeight = 0.0;

    pCamera->GetAllParameters(s_cameraType,
        position, direction, upDirection,
        aspectRatio, nearDist, farDist,
        fieldOfView,
        orthoWindowHeight);

    pCamera->SetOrtho(s_cameraType != CameraType::Ortho);

    return nullptr;
}